GitHub Actionsでactions/setup-nodeだけでnode_modulesをキャッシュできるのか試してみた
こんにちは、CX事業本部 IoT事業部の若槻です。
GitHub Actionsでは、CI/CDでよく使われる処理がActionsとして公開されており、Workflow内で自由に使うことができます。
今回は、actions/setup-nodeを使用してWorkflowの実行時にnode_modules
をキャッシュできるのか試してみました。
actions/setup-nodeとは
actions/setup-node
を使用すると、指定したバージョンのNode.js distributionのダウンロードおよびキャッシュをしたり、npm/yarn/pnpm dependencyをキャッシュしたりすることができるようです。
これを使えばWorkflow実行の高速化が期待できそうですね。
使い方
Usageを見ると使い方はこんな感じとのこと。
node-version
で指定したのNode.js distributionとsemverが一致するキャッシュが無ければダウンロードし、あればリストアして使用する。cache
を指定することにより、ルートディレクトリ配下のpackage-lock.json
(またはyarn.lock
)により生成したハッシュ値が一致すれば、Dependencyのキャッシュをリストアする。
steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 14 cache: npm - run: npm install
試してみる
それでは次のようなworkflowを使ってsetup-node
のキャッシュの動作を試してみます。
name: Caching with npm on: push jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 id: setup_node_id with: node-version: 14 cache: npm - run: echo '${{ toJSON(steps.setup_node_id.outputs) }}' - if: ${{ steps.setup_node_id.outputs.cache-hit != 'true' }} run: npm install - run: npm ls --depth=0
まず初回のworkflow実行です。
- [Run actions/setup-node@v3]で
npm cache is not found
とあり、キャッシュミスしていることが分かります。 "cache-hit": "false"
であるため、[Run npm install]でconditionがtrue
となり、npm install
が実行されています。- [Run npm ls --depth=0]で
node_modules
にDependencyがインストールされていることが確認できます。 - [Post Run actions/setup-node@v3]で
Cache saved successfully
とあり、キャッシュの保存が成功していることが分かります。
次に二回目のキャッシュを使用したworkflow実行です。
- [Run actions/setup-node@v3]で
Cache restored successfully
とあり、キャッシュからのリストアが行われていることが分かります。 "cache-hit": "true"
であるため、[Run npm install]でconditionがfalse
となり、npm install
がスキップされています。- [Run npm ls --depth=0]で
node_modules
が見つからずエラーとなっています。
どういうことなのか?
ドキュメントのCaching packages dependenciesを改めて読むと、キャッシュからDependencyがnode_modules
が復元されるかのような記述となっています。
The action has a built-in functionality for caching and restoring dependencies. It uses actions/cache under the hood for caching dependencies but requires less configuration settings. Supported package managers are npm, yarn, pnpm (v6.10+). The cache input is optional, and caching is turned off by default.
The action defaults to search for the dependency file (package-lock.json or yarn.lock) in the repository root, and uses its hash as a part of the cache key. Use cache-dependency-path for cases when multiple dependency files are used, or they are located in different subdirectories.
一方Advanced usageのCaching packages dependenciesには下記のようにあります。
The action follows actions/cache guidelines, and caches global cache on the machine instead of node_modules, so cache can be reused between different Node.js versions.
node_modules
ではなくglobal cache on the machine
がキャッシュされるとのことです。
ここで念の為確認。Workflowを次のように修正して実行。
name: Caching with npm on: push jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 id: setup_node_id with: node-version: 14 cache: npm - run: echo '${{ toJSON(steps.setup_node_id.outputs) }}' - if: ${{ steps.setup_node_id.outputs.cache-hit != 'true' }} run: npm install - run: ls -a - run: npm ls -g --depth=0 - run: npm ls --depth=0
ls -a
でカレントディレクトリ内を見るとnode_modules
はやはり作成されていません。
もしやと思いnpm ls -g --depth=0
でグローバルなnode_modules
の内容を見てみましたが、こちらにDependencyがリストアされているということはありませんでした。
global cache on the machine
の意味するところがよく分かりませんが、ドキュメントの記述に情報が少なすぎると思いました。ちなみに今年2月に下記Issueがopenされており、同様のミスリーディングをした人が他にもいるようです。勘違いしちゃいますよね…。
node_modulesのキャッシュはactions/cacheを使おう
結論としては、node_modules
のキャッシュを行いたいならactions/cache
を使えば良さそうです。
actions/setup-node
とactions/cache
を組み合わせた次のWorkfrowを試してみます。
name: Caching with npm on: push jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 14 - uses: actions/cache@v3 id: node_modules_cache_id env: cache-name: cache-node-modules with: path: '**/node_modules' key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} - run: echo '${{ toJSON(steps.node_modules_cache_id.outputs) }}' - if: ${{ steps.node_modules_cache_id.outputs.cache-hit != 'true' }} run: npm install - run: npm ls --depth=0
まず初回のworkflow実行です。
- [Run actions/setup-node@v3]で
npm cache is not found
とあり、キャッシュミスしていることが分かります。 "cache-hit": "false"
であるため、[Run npm install]でconditionがtrue
となり、npm install
が実行されています。- [Post Run actions/setup-node@v3]で
Cache saved successfully
とあり、キャッシュの保存が成功していることが分かります。
次に二回目のキャッシュを使用したworkflow実行です。
- [Run actions/setup-node@v3]で
Cache restored successfully
とあり、キャッシュからのリストアが行われていることが分かります。 "cache-hit": "true"
であるため、[Run npm install]でconditionがfalse
となり、npm install
がスキップされています。- [Run npm ls --depth=0]で、キャッシュから
node_modules
へDependencyがリストアされていることが分かります。 - [Post Run actions/setup-node@v3]で
Cache hit occurred on the primary key ..., not saving cache.
とあり、キャッシュヒットしたためキャッシュの保存がスキップされていることが分かります。
おわりに
actions/setup-nodeを使用してWorkflowの実行時にnode_modules
をキャッシュできるのか試してみました。
node_modules
をキャッシュできる前提で検証に臨んでいたため、なぜ出来ないんだろうとデバッグに相当時間を要しましたが、そもそも出来ないようでした。今後の改善でactions/setup-node
のみでnode_modules
にも対応できるようになると嬉しいですね。
参考
- Github Actions で node 環境をセットアップ
- NPM | Code Cookbook
- [GitHub]ActionsのContextを効率よく確認しつつjqとset-envを用いて再定義してみた | DevelopersIO
- Expressions - GitHub Docs
- Contexts - GitHub Docs
- GitHub Actions の Workflow を高速化する - Qiita
以上